VERSION 1.0 CLASS
BEGIN
  MultiUse = -1  'True
  Persistable = 0  'NotPersistable
  DataBindingBehavior = 0  'vbNone
  DataSourceBehavior  = 0  'vbNone
  MTSTransactionMode  = 0  'NotAnMTSObject
END
Attribute VB_Name = "ApiWindow"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = True
Attribute VB_PredeclaredId = False
Attribute VB_Exposed = False
Attribute VB_Ext_KEY = "SavedWithClassBuilder" ,"Yes"
Attribute VB_Ext_KEY = "Top_Level" ,"Yes"
Option Explicit

' ##MODULE_DESCRIPTION This class provides the properties, events and methods used _
to manipulate any given window.

' ##MODULE_DESCRIPTION Using this class and the %subclassed windows collection:EventVB~APIFunctions~SubclassedWindows% _
provides you with access to a large number of new events in addition to those that are _
exposed by Visual basic forms and also allows you to respond to events in windows that _
were not created by Visual Basic using the familiar syntax.

'\\ New window events --------------------------------------------------------------------------------------------------------------------------------------------------------------
' ##EVENT_DESCRIPTION WindowMessageFired Triggered for any message not dealt with by the other more specific events
' ##EVENT_REMARKS WindowMessageFired
Public Event WindowMessageFired(ByVal MSG As WindowMessages, ByVal wParam As Long, ByVal lParam As Long, Cancel As Boolean, ProcRet As Long)

' ##EVENT_DESCRIPTION ActiveApplicationChanged Triggered when the subclassed window is a top level window of an application and the user swicthes to or from that application (using ALT+TAB or the mouse)
' ##EVENT_REMARKS ActiveApplicationChanged This event is only fired if the window is in the thread losing the focus or the thread gaining the focus
Public Event ActiveApplicationChanged(ByVal ActivatingThisApp As Boolean, ByVal hThread As Long, Cancel As Boolean)

' ##EVENT_DESCRIPTION LostCapture Triggered when the subclassed window loses the mouse capture. _
In normal operation this occurs when the mouse leaves the window.
' ##EVENT_REMARKS LostCapture This event will not be triggered if a window has explicitly captured the mouse input.
Public Event LostCapture(ByVal hwndNewCapture As Long, Cancel As Boolean)

' ##EVENT_DESCRIPTION KeyPressed Triggered when any key is pressed whle the subclassed window has the input focus.
' ##EVENT_REMARKS KeyPressed This event provides additional information beyond the intrinsic form_Keypressed event.
Public Event KeyPressed(ByVal VKey As Long, ByVal Repetition As Long, ByVal scanCode As Long, ByVal ExtendedKey As Boolean, ByVal AltDown As Boolean, ByVal AlreadyDown As Boolean, ByVal BeingPressed As Boolean, Cancel As Boolean)

' ##EVENT_DESCRIPTION LowMemory Triggered when the available memory on a system is low and the system is required to try and compact the memory to free some space.
' ##EVENT_REMARKS LowMemory The TimeSpentCompacting increases as the memory situation gets worse.  You should free up any possible memory you can _
in response to this event.
Public Event LowMemory(ByVal TimeSpentCompacting As Long)

' ##EVENT_DESCRIPTION Move Triggered when a form is moved, by dragging or through code.
' ##EVENT_REMARKS Move The x and y parameters indicate the position of the top left corner of the window.
Public Event Move(ByVal x As Long, ByVal y As Long, Cancel As Boolean)

' ##EVENT_DESCRIPTION VerticalScroll Triggered when the user interacts with a vertical scrollbar on a window.
' ##EVENT_REMARKS VerticalScroll The message parameter tells you what operation the user performed.
Public Event VerticalScroll(ByVal Message As enScrollMessages, ByVal Position As Long, Cancel As Boolean)

' ##EVENT_DESCRIPTION HorizontalScroll Triggered when the user interacts with a horizontal scrollbar on a window.
' ##EVENT_REMARKS HorizontalScroll The message parameter tells you what operation the user performed.
Public Event HorizontalScroll(ByVal Message As enScrollMessages, ByVal Position As Long, Cancel As Boolean)

' ##EVENT_DESCRIPTION WindowsSettingsChanged Triggered when the system settings changed.
' ##EVENT_REMARKS WindowsSettingsChanged newSetting describes which type of setting changed.
Public Event WindowsSettingsChanged(ByVal newSetting As enSystemParametersInfo)

' ##EVENT_DESCRIPTION WindowsINIChanged Triggered when a setting stored in the WIN.INI is changed.
' ##EVENT_REMARKS WindowsINIChanged Section is the major section e.g. [INTL] that has been changed
Public Event WindowsINIChanged(ByVal Section As String)

' ##EVENT_DESCRIPTION NonClientMouseMove Triggered when the mouse is moved over the non client area of the window.
' ##EVENT_REMARKS NonClientMouseMove The non client area includes the caption bar, menu bar etc.
Public Event NonClientMouseMove(ByVal Location As enHitTestResult, ByVal x As Single, ByVal y As Single)

' ##EVENT_DESCRIPTION NonClientMouseDown Triggered when the mouse button is pressed while the cursor is over a non client part of the window.
' ##EVENT_REMARKS NonClientMouseDown The non client area includes the caption bar, menu bar etc.
Public Event NonClientMouseDown(ByVal Location As enHitTestResult, ByVal Button As Integer, ByVal x As Single, ByVal y As Single)

' ##EVENT_DESCRIPTION NonClientMouseUp Triggered when the mouse button is released while the cursor is over a non client part of the window.
' ##EVENT_REMARKS NonClientMouseUp The non client area includes the caption bar, menu bar etc.
Public Event NonClientMouseUp(ByVal Location As enHitTestResult, ByVal Button As Integer, ByVal x As Single, ByVal y As Single)

' ##EVENT_DESCRIPTION NonClientDblClick Triggered when the mouse button is double-clicked while the cursor is over a non client part of the window.
' ##EVENT_REMARKS NonClientDblClick The non client area includes the caption bar, menu bar etc.
Public Event NonClientDblClick(ByVal Location As enHitTestResult, ByVal Button As Integer, ByVal x As Single, ByVal y As Single)

' ##EVENT_DESCRIPTION MinMaxSize Triggered when the operating system wishes to know the minimum and maximum sizes of the window.
' ##EVENT_REMARKS MinMaxSize Changing any of the min or max values will prevent the window being resized outside of that size. _
This is very useful for creating docking style windows.
Public Event MinMaxSize(MaxHeight As Long, MaxWidth As Long, MaxPositionTop As Long, MaxPositionLeft As Long, MinTrackWidth As Long, MinTrackheight As Long, MaxTrackWidth As Long, MaxTrackHeight As Long)

' ##EVENT_DESCRIPTION MouseOverMenu Triggered when the mouse is moved over a top level menu bar item.
' ##EVENT_REMARKS MouseOverMenu You can use this event to provide feedback to the user about what a given menu is used for.
Public Event MouseOverMenu(ByVal Caption As String)

' ##EVENT_DESCRIPTION Hotkey Triggered when a %hotkey:EventVB~ApiHotkey% that has been registered for this window is pressed.
' ##EVENT_REMARKS Hotkey Currently a window can only have one hotkey registered to it at any time.
Public Event Hotkey(ByVal Hotkey As ApiHotkey)

' ##EVENT_DESCRIPTION Paint Triggered when all or part of the form needs to be repainted.
' ##EVENT_REMARKS Paint Use this event for owner drawn controls, for example.
Public Event Paint(ByVal UpdateRect As APIRect)

' ##EVENT_DESCRIPTION NonClientPaint Triggered when all or part of the non client area needs to be repainted.
' ##EVENT_REMARKS NonClientPaint This event can be used to implement customised non client areas - like skins.
Public Event NonClientPaint(ByVal NonClientDeviceContext As ApiDeviceContext)

' ##EVENT_DESCRIPTION HitTest Triggered when windows wants to know what part of the form the mouse is over (client, caption., menu etc.)
' ##EVENT_REMARKS HitTest Overriding this event alters the way windows behaves.  Using this you can allow a window with no border to be _
moved or resized, for example.
Public Event HitTest(ByVal x As Long, ByVal y As Long, ReturnValue As enHitTestResult, Override As Boolean)


Private m_hwnd As Long

'\\ API Declarations -------------------------------------------------------------------------------------------------------------------------------------------------------
Private Declare Function IsWindowApi Lib "user32" Alias "IsWindow" (ByVal hWnd As Long) As Long
Private Declare Function GetParentApi Lib "user32" Alias "GetParent" (ByVal hWnd As Long) As Long
Private Declare Function WindowFromPointApi Lib "user32" Alias "WindowFromPoint" (ByVal xPoint As Long, ByVal yPoint As Long) As Long
Private Declare Function GetWindowApi Lib "user32" Alias "GetWindow" (ByVal hWnd As Long, ByVal wCmd As Long) As Long
Private Declare Function IsWindowEnabledApi Lib "user32" Alias "IsWindowEnabled" (ByVal hWnd As Long) As Long
Private Declare Function IsWindowUnicodeApi Lib "user32" Alias "IsWindowUnicode" (ByVal hWnd As Long) As Long
Private Declare Function IsWindowVisibleApi Lib "user32" Alias "IsWindowVisible" (ByVal hWnd As Long) As Long
Private Declare Function IsZoomedApi Lib "user32" Alias "IsZoomed" (ByVal hWnd As Long) As Long
'\\ Window specific information
Private Declare Function GetWindowLongApi Lib "user32" Alias "GetWindowLongA" (ByVal hWnd As Long, ByVal nIndex As Long) As Long
Private Declare Function SetWindowLongApi Lib "user32" Alias "SetWindowLongA" (ByVal hWnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
'\\ Menu specific....
Private Declare Function GetSystemMenuApi Lib "user32" Alias "GetSystemMenu" (ByVal hWnd As Long, ByVal bRevert As Long) As Long
Private Declare Function GetMenuApi Lib "user32" Alias "GetMenu" (ByVal hWnd As Long) As Long
'\\ Device context specific....
Private Declare Function GetDCApi Lib "user32" Alias "GetDC" (ByVal hWnd As Long) As Long
Private Declare Function GetWindowDC Lib "user32" (ByVal hWnd As Long) As Long
'\\ Window class specific...
Private Declare Function GetClassNameApi Lib "user32" Alias "GetClassNameA" (ByVal hWnd As Long, ByVal lpClassName As String, ByVal nMaxCount As Long) As Long
'\\ Send message....
Private Declare Function SendMessageLong Lib "user32" Alias "SendMessageA" (ByVal hWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Private Declare Function InvalidateRectByPointerApi Lib "user32" Alias "InvalidateRect" (ByVal hWnd As Long, ByVal lpRect As Long, ByVal bErase As Long) As Long
'\\ Scrolling....
Private Type RECT
    Left As Long
    Top As Long
    Right As Long
    Bottom As Long
End Type
Private Declare Function GetWindowRectApi Lib "user32" Alias "GetWindowRect" (ByVal hWnd As Long, lpRect As RECT) As Long
Private Declare Function ScrollWindowExAPI Lib "user32" Alias "ScrollWindowEx" (ByVal hWnd As Long, ByVal dX As Long, ByVal dY As Long, ByVal lprcScroll As Long, ByVal lprcClip As Long, ByVal hrgnUpdate As Long, lprcUpdate As RECT, ByVal fuScroll As Long) As Long
'\\ Mouse message capture
Private Declare Function SetCaptureApi Lib "user32" Alias "SetCapture" (ByVal hWnd As Long) As Long
Private Declare Function GetCaptureApi Lib "user32" Alias "GetCapture" () As Long
'\\ Windows regions.....
Private Declare Function GetWindowRgn Lib "user32" (ByVal hWnd As Long, ByVal hRgn As Long) As Long
Private Declare Function SetWindowRgn Lib "user32" (ByVal hWnd As Long, ByVal hRgn As Long, ByVal bRedraw As Boolean) As Long
'\\ Refreshing the window states....
Private Declare Function DrawMenuBarApi Lib "user32" Alias "DrawMenuBar" (ByVal hWnd As Long) As Long
'\\ Window text...
Private Declare Function GetWindowTextLengthApi Lib "user32" Alias "GetWindowTextLengthA" (ByVal hWnd As Long) As Long
Private Declare Function GetWindowTextApi Lib "user32" Alias "GetWindowTextA" (ByVal hWnd As Long, ByVal lpString As String, ByVal cch As Long) As Long
'\\ Painting the window,
Private Declare Function GetUpdateRect Lib "user32" (ByVal hWnd As Long, lpRect As RECT, ByVal bErase As Long) As Long
Private Declare Function UpdateWindow Lib "user32" (ByVal hWnd As Long) As Long

'\\ Non-client area painting...
Private Declare Function GetDCEx Lib "user32" (ByVal hWnd As Long, ByVal hrgnclip As Long, ByVal fdwOptions As Long) As Long
Public Enum ExtendedDeviceContextIndexes
    DCX_WINDOW = &H1
    DCX_CACHE = &H2
    DCX_NORESETATTRS = &H4
    DCX_CLIPCHILDREN = &H8
    DCX_CLIPSIBLINGS = &H10
    DCX_PARENTCLIP = &H20
    DCX_EXCLUDERGN = &H40
    DCX_INTERSECTRGN = &H80
    DCX_EXCLUDEUPDATE = &H100
    DCX_INTERSECTUPDATE = &H200
    DCX_LOCKWINDOWUPDATE = &H400
    DCX_VALIDATE = &H200000
End Enum

'\\ Set window pos...
Private Declare Function SetWindowPos Lib "user32" (ByVal hWnd As Long, ByVal hWndInsertAfter As Long, ByVal x As Long, ByVal y As Long, ByVal cx As Long, ByVal cy As Long, ByVal wFlags As Long) As Long
Private Declare Function ScreenToClient Lib "user32" (ByVal hWnd As Long, lpPoint As POINTAPI) As Long

Public Enum enSetWindowPos
    SWP_FRAMECHANGED = &H20        '  The frame changed: send WM_NCCALCSIZE
    SWP_HIDEWINDOW = &H80
    SWP_NOACTIVATE = &H10
    SWP_NOCOPYBITS = &H100
    SWP_NOMOVE = &H2
    SWP_NOOWNERZORDER = &H200      '  Don't do owner Z ordering
    SWP_NOREDRAW = &H8
    SWP_NOSIZE = &H1
    SWP_NOZORDER = &H4
    SWP_SHOWWINDOW = &H40
End Enum

'\\ Getting information about a window's title bar...
Public Enum WindowSystemStates
    STATE_SYSTEM_UNAVAILABLE = &H1                '\\ Disabled
    STATE_SYSTEM_SELECTED = &H2
    STATE_SYSTEM_FOCUSED = &H4
    STATE_SYSTEM_PRESSED = &H8
    STATE_SYSTEM_CHECKED = &H10
    STATE_SYSTEM_MIXED = &H20                     '\\ 3-state checkbox or toolbar button
    STATE_SYSTEM_READONLY = &H40
    STATE_SYSTEM_HOTTRACKED = &H80
    STATE_SYSTEM_DEFAULT = &H100
    STATE_SYSTEM_EXPANDED = &H200
    STATE_SYSTEM_COLLAPSED = &H400
    STATE_SYSTEM_BUSY = &H800
    STATE_SYSTEM_FLOATING = &H1000                '\\ Children "owned" not "contained" by parent
    STATE_SYSTEM_MARQUEED = &H2000
    STATE_SYSTEM_ANIMATED = &H4000
    STATE_SYSTEM_INVISIBLE = &H8000
    STATE_SYSTEM_OFFSCREEN = &H10000
    STATE_SYSTEM_SIZEABLE = &H20000
    STATE_SYSTEM_MOVEABLE = &H40000
    STATE_SYSTEM_SELFVOICING = &H80000
    STATE_SYSTEM_FOCUSABLE = &H100000
    STATE_SYSTEM_SELECTABLE = &H200000
    STATE_SYSTEM_LINKED = &H400000
    STATE_SYSTEM_TRAVERSED = &H800000
    STATE_SYSTEM_MULTISELECTABLE = &H1000000      '\\ Supports multiple selection
    STATE_SYSTEM_EXTSELECTABLE = &H2000000        '\\ Supports extended selection
    STATE_SYSTEM_ALERT_LOW = &H4000000            '\\ This information is of low priority
    STATE_SYSTEM_ALERT_MEDIUM = &H8000000         '\\ This information is of medium priority
    STATE_SYSTEM_ALERT_HIGH = &H10000000          '\\ This information is of high priority
    STATE_SYSTEM_VALID = &H1FFFFFFF
End Enum

Private Type TITLEBARINFO
    cbSize As Long '\\ Size of this structure
    rcTitleBar As RECT '\\ Rectangle of the whole title bar except menu..
    rgstate(0 To 5) As Long '\\ Each is a combination of window_system_states
End Type
Private Declare Function GetTitleBarInfo Lib "user32" (ByVal hWnd As Long, lpTileBarInfo As TITLEBARINFO) As Long




'\\ Private member variables ----------------------------------------------------------------------------------------------------------------------------------------------------------
Private mOldProcAddress As Long
Private mPrevCapture As Long
'\\ Objects....
Private mSystemMenu As ApiMenu
Private mMenu As ApiMenu
Private mWndClass As APIWndClass
Private mRegion As ApiRegion
Private mDeviceContext As ApiDeviceContext
Private mDeviceContextNC As ApiDeviceContext

'\\ Setting of minmaxinfo....
Private Type POINTAPI
    x As Long
    y As Long
End Type

Private Type MINMAXINFO
    ptReserved As POINTAPI
    ptMaxSize As POINTAPI
    ptMaxPosition As POINTAPI
    ptMinTrackSize As POINTAPI
    ptMaxTrackSize As POINTAPI
End Type


'\\ Memory manipulation routines for min/max info
Private Declare Sub CopyMemoryMinMaxInfo Lib "kernel32" Alias "RtlMoveMemory" (Destination As MINMAXINFO, ByVal Source As Long, ByVal Length As Long)
Private Declare Sub CopyMinMaxToMemoryInfo Lib "kernel32" Alias "RtlMoveMemory" (ByVal Destination As Long, Source As MINMAXINFO, ByVal Length As Long)

'\\ message passing
Private Declare Function SendMessageByLong Lib "user32" Alias "SendMessageA" (ByVal hWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Private Declare Function SendMessageByString Lib "user32" Alias "SendMessageA" (ByVal hWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As String) As Long

'\\ Threads...
Private Declare Function GetWindowThreadProcessId Lib "user32" (ByVal hWnd As Long, lpdwProcessId As Long) As Long

Public Enum enComboBoxNotifications
    CBN_CLOSEUP = 8
    CBN_DBLCLK = 2
    CBN_DROPDOWN = 7
    CBN_EDITCHANGE = 5
    CBN_EDITUPDATE = 6
    CBN_ERRSPACE = (-1)
    CBN_KILLFOCUS = 4
    CBN_SELCHANGE = 1
    CBN_SELENDCANCEL = 10
    CBN_SELENDOK = 9
    CBN_SETFOCUS = 3
End Enum

Public Enum enListBoxNotifications
    LBN_DBLCLK = 2
    LBN_ERRSPACE = (-2)
    LBN_KILLFOCUS = 5
    LBN_SELCANCEL = 3
    LBN_SELCHANGE = 1
    LBN_SETFOCUS = 4
End Enum

Public Enum enEditBoxNotifications
    EN_CHANGE = &H300
    EN_ERRSPACE = &H500
    EN_HSCROLL = &H601
    EN_KILLFOCUS = &H200
    EN_MAXTEXT = &H501
    EN_SETFOCUS = &H100
    EN_UPDATE = &H400
    EN_VSCROLL = &H602
End Enum

Public Enum enCommonControlGenericNotifications
    NM_OUTOFMEMORY = (-1)
    NM_CLICK = (-2)                  ''\\ uses NMCLICK struct
    NM_DBLCLK = (-3)
    NM_RETURN = (-4)
    NM_RCLICK = (-5)                 ''\\ uses NMCLICK struct
    NM_RDBLCLK = (-6)
    NM_SETFOCUS = (-7)
    NM_KILLFOCUS = (-8)
    NM_CUSTOMDRAW = (-12)
    NM_HOVER = (-13)
    NM_NCHITTEST = (-14)             ''\\ uses NMMOUSE struct
    NM_KEYDOWN = (-15)               ''\\ uses NMKEY struct
    NM_RELEASEDCAPTURE = (-16)
    NM_SETCURSOR = (-17)             ''\\ uses NMMOUSE struct
    NM_CHAR = (-18)                  ''\\ uses NMCHAR struct
End Enum

Private Const LVN_FIRST = -100
Public Enum enListviewNotificationMessages
    LVN_ITEMCHANGING = (LVN_FIRST - 0)
    LVN_ITEMCHANGED = (LVN_FIRST - 1)
    LVN_INSERTITEM = (LVN_FIRST - 2)
    LVN_DELETEITEM = (LVN_FIRST - 3)
    LVN_DELETEALLITEMS = (LVN_FIRST - 4)
    LVN_BEGINLABELEDITA = (LVN_FIRST - 5)
    LVN_BEGINLABELEDITW = (LVN_FIRST - 75)
    LVN_ENDLABELEDITA = (LVN_FIRST - 6)
    LVN_ENDLABELEDITW = (LVN_FIRST - 76)
    LVN_COLUMNCLICK = (LVN_FIRST - 8)
    LVN_BEGINDRAG = (LVN_FIRST - 9)
    LVN_BEGINRDRAG = (LVN_FIRST - 11)
    LVN_ODCACHEHINT = (LVN_FIRST - 13)
    LVN_ODFINDITEMA = (LVN_FIRST - 52)
    LVN_ODFINDITEMW = (LVN_FIRST - 79)
    LVN_ITEMACTIVATE = (LVN_FIRST - 14)
    LVN_ODSTATECHANGED = (LVN_FIRST - 15)
End Enum

Private Const HDN_FIRST = -300
Public Enum enHeaderNotificationMessages
    HDN_ITEMCHANGINGA = (HDN_FIRST - 0)
    HDN_ITEMCHANGINGW = (HDN_FIRST - 20)
    HDN_ITEMCHANGEDA = (HDN_FIRST - 1)
    HDN_ITEMCHANGEDW = (HDN_FIRST - 21)
    HDN_ITEMCLICKA = (HDN_FIRST - 2)
    HDN_ITEMCLICKW = (HDN_FIRST - 22)
    HDN_ITEMDBLCLICKA = (HDN_FIRST - 3)
    HDN_ITEMDBLCLICKW = (HDN_FIRST - 23)
    HDN_DIVIDERDBLCLICKA = (HDN_FIRST - 5)
    HDN_DIVIDERDBLCLICKW = (HDN_FIRST - 25)
    HDN_BEGINTRACKA = (HDN_FIRST - 6)
    HDN_BEGINTRACKW = (HDN_FIRST - 26)
    HDN_ENDTRACKA = (HDN_FIRST - 7)
    HDN_ENDTRACKW = (HDN_FIRST - 27)
    HDN_TRACKA = (HDN_FIRST - 8)
    HDN_TRACKW = (HDN_FIRST - 28)
    HDN_GETDISPINFOA = (HDN_FIRST - 9)
    HDN_GETDISPINFOW = (HDN_FIRST - 29)
    HDN_BEGINDRAG = (HDN_FIRST - 10)
    HDN_ENDDRAG = (HDN_FIRST - 11)
End Enum

Private Const TVN_FIRST = -400
Public Enum enTreeviewNotificationMessages
    TVN_SELCHANGINGA = (TVN_FIRST - 1)
    TVN_SELCHANGINGW = (TVN_FIRST - 50)
    TVN_SELCHANGEDA = (TVN_FIRST - 2)
    TVN_SELCHANGEDW = (TVN_FIRST - 51)
    TVN_GETDISPINFOA = (TVN_FIRST - 3)
    TVN_GETDISPINFOW = (TVN_FIRST - 52)
    TVN_SETDISPINFOA = (TVN_FIRST - 4)
    TVN_SETDISPINFOW = (TVN_FIRST - 53)
    TVN_ITEMEXPANDINGA = (TVN_FIRST - 5)
    TVN_ITEMEXPANDINGW = (TVN_FIRST - 54)
    TVN_ITEMEXPANDEDA = (TVN_FIRST - 6)
    TVN_ITEMEXPANDEDW = (TVN_FIRST - 55)
    TVN_BEGINDRAGA = (TVN_FIRST - 7)
    TVN_BEGINDRAGW = (TVN_FIRST - 56)
    TVN_BEGINRDRAGA = (TVN_FIRST - 8)
    TVN_BEGINRDRAGW = (TVN_FIRST - 57)
    TVN_DELETEITEMA = (TVN_FIRST - 9)
    TVN_DELETEITEMW = (TVN_FIRST - 58)
    TVN_BEGINLABELEDITA = (TVN_FIRST - 10)
    TVN_BEGINLABELEDITW = (TVN_FIRST - 59)
    TVN_ENDLABELEDITA = (TVN_FIRST - 11)
    TVN_ENDLABELEDITW = (TVN_FIRST - 60)
    TVN_KEYDOWN = (TVN_FIRST - 12)
    TVN_GETINFOTIPA = (TVN_FIRST - 13)
    TVN_GETINFOTIPW = (TVN_FIRST - 14)
    TVN_SINGLEEXPAND = (TVN_FIRST - 15)
End Enum

Private Const TTN_FIRST = -520
Public Enum enToolTipNotificationMessages
    TTN_GETDISPINFOA = (TTN_FIRST - 0)
    TTN_GETDISPINFOW = (TTN_FIRST - 10)
    TTN_SHOW = (TTN_FIRST - 1)
    TTN_POP = (TTN_FIRST - 2)
End Enum

Private Const TCN_FIRST = -550
Public Enum enTabControlNotificationMessages
    TCN_KEYDOWN = (TCN_FIRST - 0)
    TCN_SELCHANGE = (TCN_FIRST - 1)
    TCN_SELCHANGING = (TCN_FIRST - 2)
    TCN_GETOBJECT = (TCN_FIRST - 3)
End Enum

Private Const CDN_FIRST = -601
Public Enum enCommonDialogNotificationMessages
    CDN_INITDONE = (CDN_FIRST - &H0)
    CDN_SELCHANGE = (CDN_FIRST - &H1)
    CDN_FOLDERCHANGE = (CDN_FIRST - &H2)
    CDN_SHAREVIOLATION = (CDN_FIRST - &H3)
    CDN_HELP = (CDN_FIRST - &H4)
    CDN_FILEOK = (CDN_FIRST - &H5)
    CDN_TYPECHANGE = (CDN_FIRST - &H6)
    CDN_INCLUDEITEM = (CDN_FIRST - &H7)
End Enum

Private Const TBN_FIRST = -700
Public Enum enToolbarNotificationMessages
    TBN_GETBUTTONINFOA = (TBN_FIRST - 0)
    TBN_GETBUTTONINFOW = (TBN_FIRST - 20)
    TBN_BEGINDRAG = (TBN_FIRST - 1)
    TBN_ENDDRAG = (TBN_FIRST - 2)
    TBN_BEGINADJUST = (TBN_FIRST - 3)
    TBN_ENDADJUST = (TBN_FIRST - 4)
    TBN_RESET = (TBN_FIRST - 5)
    TBN_QUERYINSERT = (TBN_FIRST - 6)
    TBN_QUERYDELETE = (TBN_FIRST - 7)
    TBN_TOOLBARCHANGE = (TBN_FIRST - 8)
    TBN_CUSTHELP = (TBN_FIRST - 9)
    TBN_DROPDOWN = (TBN_FIRST - 10)
    TBN_GETOBJECT = (TBN_FIRST - 12)
    TBN_HOTITEMCHANGE = (TBN_FIRST - 13)
    TBN_DRAGOUT = (TBN_FIRST - 14)            ''\\ this is sent when the user clicks down on a button then drags off the button
    TBN_DELETINGBUTTON = (TBN_FIRST - 15)     ''\\ uses TBNOTIFY
    TBN_GETDISPINFOA = (TBN_FIRST - 16)       ''\\ This is sent when the  toolbar needs  some display information
    TBN_GETDISPINFOW = (TBN_FIRST - 17)       ''\\ This is sent when the  toolbar needs  some display information
    TBN_GETINFOTIPA = (TBN_FIRST - 18)
    TBN_GETINFOTIPW = (TBN_FIRST - 19)
End Enum

Private Const UDN_FIRST = -721
Public Enum enUpDownNotificationMessages
    UDN_DELTAPOS = (UDN_FIRST - 1)
End Enum

Private Const MCN_FIRST = -750
Public Enum enMonthCalendarNotificationMessages
    MCN_SELCHANGE = (MCN_FIRST + 1)
    MCN_GETDAYSTATE = (MCN_FIRST + 3)
    MCN_SELECT = (MCN_FIRST + 4)
End Enum

Private Const DTN_FIRST = -760
Public Enum enDateTimeNotificationMessages
    DTN_DATETIMECHANGE = (DTN_FIRST + 1)
    DTN_USERSTRINGA = (DTN_FIRST + 2) ''\\ the user has entered a string
    DTN_USERSTRINGW = (DTN_FIRST + 15)
    DTN_WMKEYDOWNA = (DTN_FIRST + 3) ''\\ modify keydown on app format field (X)
    DTN_WMKEYDOWNW = (DTN_FIRST + 16)
    DTN_FORMATA = (DTN_FIRST + 4) ''\\ query display for app format field (X)
    DTN_FORMATW = (DTN_FIRST + 17)
    DTN_FORMATQUERYA = (DTN_FIRST + 5) ''\\ query formatting info for app format field (X)
    DTN_FORMATQUERYW = (DTN_FIRST + 18)
    DTN_DROPDOWN = (DTN_FIRST + 6)   ''\\ MonthCal has dropped down
    DTN_CLOSEUP = (DTN_FIRST + 7)    ''\\ MonthCal is popping up
End Enum

Private Const CBEN_FIRST = -800
Public Enum enComboBoxExtendedNotificationMessages
    CBEN_GETDISPINFO = (CBEN_FIRST - 0)
    CBEN_INSERTITEM = (CBEN_FIRST - 1)
    CBEN_DELETEITEM = (CBEN_FIRST - 2)
    CBEN_BEGINEDIT = (CBEN_FIRST - 4)
    CBEN_ENDEDITA = (CBEN_FIRST - 5)
    CBEN_ENDEDITW = (CBEN_FIRST - 6)
    CBEN_GETDISPINFOW = (CBEN_FIRST - 7)
    CBEN_DRAGBEGINA = (CBEN_FIRST - 8)
    CBEN_DRAGBEGINW = (CBEN_FIRST - 9)
End Enum

Private Const RBN_FIRST = -831
Public Enum enCoolbarNotificationMessages
    RBN_HEIGHTCHANGE = (RBN_FIRST - 0)
    RBN_GETOBJECT = (RBN_FIRST - 1)
    RBN_LAYOUTCHANGED = (RBN_FIRST - 2)
    RBN_AUTOSIZE = (RBN_FIRST - 3)
    RBN_BEGINDRAG = (RBN_FIRST - 4)
    RBN_ENDDRAG = (RBN_FIRST - 5)
    RBN_DELETINGBAND = (RBN_FIRST - 6)       ''\\ Uses NMREBAR
    RBN_DELETEDBAND = (RBN_FIRST - 7)        ''\\ Uses NMREBAR
    RBN_CHILDSIZE = (RBN_FIRST - 8)
End Enum

Private Const SBN_FIRST = -880
Public Enum enStatusBarNotificationMessages
    SBN_SIMPLEMODECHANGE = (SBN_FIRST - 0)
End Enum

Public Enum ButtonMessages
    BM_GETCHECK = &HF0
    BM_SETCHECK = &HF1
    BM_GETSTATE = &HF2
    BM_SETSTATE = &HF3
    BM_SETSTYLE = &HF4
    BM_CLICK = &HF5
    BM_GETIMAGE = &HF6
    BM_SETIMAGE = &HF7
End Enum

Public Enum ButtonStates
     BST_UNCHECKED = &H0
     BST_CHECKED = &H1
     BST_INDETERMINATE = &H2
     BST_PUSHED = &H4
     BST_FOCUS = &H8
End Enum

Private mThreadParent As Long


'\\ Get relative window constants
Public Enum enGetWindow
    GW_HWNDFIRST = 0
    GW_HWNDLAST = 1
    GW_HWNDNEXT = 2
    GW_HWNDPREV = 3
    GW_OWNER = 4
    GW_CHILD = 5
End Enum

'\\ Window Style
' ##ENUMERATION_DESCRIPTION These style bits are combined to define what style elements the _
window that is created with them will have.
Public Enum enWindowStyles
    ' ##ENUMERATION_MEMBER_DESCRIPTION WS_BORDER The window has a frame border around it
    WS_BORDER = &H800000
    ' ##ENUMERATION_MEMBER_DESCRIPTION WS_CAPTION The window has a caption title bar
    WS_CAPTION = &HC00000
    ' ##ENUMERATION_MEMBER_DESCRIPTION WS_CHILD The window is a child (non top level) window
    WS_CHILD = &H40000000
    ' ##ENUMERATION_MEMBER_DESCRIPTION WS_CLIPCHILDREN The window cannot draw over other windows that are its children
    WS_CLIPCHILDREN = &H2000000
    ' ##ENUMERATION_MEMBER_DESCRIPTION WS_CLIPSIBLINGS This window's child windows cannot draw over each other
    WS_CLIPSIBLINGS = &H4000000
    ' ##ENUMERATION_MEMBER_DESCRIPTION WS_DISABLED The window is disabled and cannot accept imput
    WS_DISABLED = &H8000000
    ' ##ENUMERATION_MEMBER_DESCRIPTION WS_DLGFRAME The window has a double border but no caption
    WS_DLGFRAME = &H400000
    ' ##ENUMERATION_MEMBER_DESCRIPTION WS_EX_ACCEPTFILES The window will accept files being dropped on it from Explorer
    WS_EX_ACCEPTFILES = &H10&
    ' ##ENUMERATION_MEMBER_DESCRIPTION WS_EX_DLGMODALFRAME The window has a double border and may have a caption
    WS_EX_DLGMODALFRAME = &H1&
    ' ##ENUMERATION_MEMBER_DESCRIPTION WS_EX_NOPARENTNOTIFY The window will not send a message to its parent (if any) when it is destroyed
    WS_EX_NOPARENTNOTIFY = &H4&
    ' ##ENUMERATION_MEMBER_DESCRIPTION WS_EX_TOPMOST The window will float over non topmost windows
    WS_EX_TOPMOST = &H8&
    ' ##ENUMERATION_MEMBER_DESCRIPTION WS_EX_TRANSPARENT The window does not obscure windows behind it
    WS_EX_TRANSPARENT = &H20&
    ' ##ENUMERATION_MEMBER_DESCRIPTION WS_EX_TOOLWINDOW The window has a toolbox look (smaller caption bar)
    WS_EX_TOOLWINDOW = &H80&
    ' ##ENUMERATION_MEMBER_DESCRIPTION WS_GROUP The window is the first of a group of windows in a dialog box
    WS_GROUP = &H20000
    ' ##ENUMERATION_MEMBER_DESCRIPTION WS_HSCROLL The window has a horizontal scroll bar
    WS_HSCROLL = &H100000
    ' ##ENUMERATION_MEMBER_DESCRIPTION WS_MAXIMIZE The window is maximised when first created
    WS_MAXIMIZE = &H1000000
    ' ##ENUMERATION_MEMBER_DESCRIPTION WS_MAXIMIZEBOX The window has a maximise box
    WS_MAXIMIZEBOX = &H10000
    ' ##ENUMERATION_MEMBER_DESCRIPTION WS_MINIMIZE The window is minimised when first created
    WS_MINIMIZE = &H20000000
    ' ##ENUMERATION_MEMBER_DESCRIPTION WS_MINIMIZEBOX The window has a minimise box
    WS_MINIMIZEBOX = &H20000
    ' ##ENUMERATION_MEMBER_DESCRIPTION WS_OVERLAPPED The window is a standard top level (application) window
    WS_OVERLAPPED = &H0&
    ' ##ENUMERATION_MEMBER_DESCRIPTION WS_POPUP The window is a popup type window
    WS_POPUP = &H80000000
    ' ##ENUMERATION_MEMBER_DESCRIPTION WS_SYSMENU The window has a system menu box
    WS_SYSMENU = &H80000
    ' ##ENUMERATION_MEMBER_DESCRIPTION WS_TABSTOP The window accepts the focus when tabbed to
    WS_TABSTOP = &H10000
    ' ##ENUMERATION_MEMBER_DESCRIPTION WS_THICKFRAME The window has a resizeable window style thick border
    WS_THICKFRAME = &H40000
    ' ##ENUMERATION_MEMBER_DESCRIPTION WS_VISIBLE The window is visible
    WS_VISIBLE = &H10000000
    ' ##ENUMERATION_MEMBER_DESCRIPTION WS_VSCROLL The window has a vertical scroll bar
    WS_VSCROLL = &H200000
    '\\ New from 95/NT4 onwards
    ' ##ENUMERATION_MEMBER_DESCRIPTION WS_EX_MDICHILD The window is an MDI child style window
    WS_EX_MDICHILD = &H40
    ' ##ENUMERATION_MEMBER_DESCRIPTION WS_EX_WINDOWEDGE The window has a beveled outer edge
    WS_EX_WINDOWEDGE = &H100
    ' ##ENUMERATION_MEMBER_DESCRIPTION WS_EX_CLIENTEDGE The window has a chiselled inner edge
    WS_EX_CLIENTEDGE = &H200
    ' ##ENUMERATION_MEMBER_DESCRIPTION WS_EX_CONTEXTHELP The window supports context sensitive help
    WS_EX_CONTEXTHELP = &H400
    ' ##ENUMERATION_MEMBER_DESCRIPTION WS_EX_RIGHT Text in this window is right aligned (if WS_EX_RTLREADING is set)
    WS_EX_RIGHT = &H1000
    ' ##ENUMERATION_MEMBER_DESCRIPTION WS_EX_LEFT Test in this window is left aligned
    WS_EX_LEFT = &H0
    ' ##ENUMERATION_MEMBER_DESCRIPTION WS_EX_RTLREADING Arranges text for right to left reading (for Hebrew or Arabic for example)
    WS_EX_RTLREADING = &H2000
    ' ##ENUMERATION_MEMBER_DESCRIPTION WS_EX_LTRREADING Arranges text for left to right reading
    WS_EX_LTRREADING = &H0
    ' ##ENUMERATION_MEMBER_DESCRIPTION WS_EX_LEFTSCROLLBAR Scrollbar on the left hand side (if WS_EX_RTLREADING is set)
    WS_EX_LEFTSCROLLBAR = &H4000
    ' ##ENUMERATION_MEMBER_DESCRIPTION WS_EX_RIGHTSCROLLBAR Scrollbar on the right hand side
    WS_EX_RIGHTSCROLLBAR = &H0
    ' ##ENUMERATION_MEMBER_DESCRIPTION WS_EX_CONTROLPARENT causes child windows of this window to have a tab order
    WS_EX_CONTROLPARENT = &H10000
    ' ##ENUMERATION_MEMBER_DESCRIPTION WS_EX_STATICEDGE Make sthe window a 3D style frame window
    WS_EX_STATICEDGE = &H20000
    ' ##ENUMERATION_MEMBER_DESCRIPTION WS_EX_APPWINDOW Minimises to the task bar
    WS_EX_APPWINDOW = &H40000
    ' ##ENUMERATION_MEMBER_DESCRIPTION WS_EX_OVERLAPPEDWINDOW Has a raised edge around it like an application window
    WS_EX_OVERLAPPEDWINDOW = (WS_EX_WINDOWEDGE Or WS_EX_CLIENTEDGE)
    ' ##ENUMERATION_MEMBER_DESCRIPTION WS_EX_PALETTEWINDOW Is a floating toolbar or palette style window
    WS_EX_PALETTEWINDOW = (WS_EX_WINDOWEDGE Or WS_EX_TOOLWINDOW Or WS_EX_TOPMOST)
End Enum

'\\ This is in the wParam of WM_POWER and DRV_POWER messages
Public Enum PowerStatusChangeMessages
     PWR_OK = 1
     PWR_FAIL = (-1)
     PWR_SUSPENDREQUEST = 1
     PWR_SUSPENDRESUME = 2
     PWR_CRITICALRESUME = 3
End Enum

'\\ This is in wParam of WM_SIZING messages
Public Enum WindowSizingMessages
     WMSZ_LEFT = 1
     WMSZ_RIGHT = 2
     WMSZ_TOP = 3
     WMSZ_TOPLEFT = 4
     WMSZ_TOPRIGHT = 5
     WMSZ_BOTTOM = 6
     WMSZ_BOTTOMLEFT = 7
     WMSZ_BOTTOMRIGHT = 8
End Enum

'\\ This is in wParam of WM_SIZE messages
Public Enum WindowSizeMessages
     SIZE_RESTORED = 0
     SIZE_MINIMIZED = 1
     SIZE_MAXIMIZED = 2
     SIZE_MAXSHOW = 3
     SIZE_MAXHIDE = 4
End Enum

'\\ Before WM_MOUSEHOVER and WM_MOUSELEAVE messages can be generated for
'\\ a window, the message tracking must be enabled on that window
Public Enum TrackMouseEvents
     TME_HOVER = &H1
     TME_LEAVE = &H2
     TME_QUERY = &H40000000
     TME_CANCEL = &H80000000
End Enum

Private Type TRACKMOUSESTRUCT
    cbSize As Long
    dwFlags As Long '\\ TrackMouseEvents
    hwndTrack As Long '\\ Target window
    dwHoverTime As Long '\\ Mouse hover timeout in milliseconds
End Type

Private Declare Function TrackMouseEvent Lib "user32" (lpTrackMouseStruct As TRACKMOUSESTRUCT) As Long

Public Property Get BorderHeight() As Long

If BorderStyle = vbBSNone Then
    BorderHeight = 0
Else
    If IsWindowStyleSet(WS_THICKFRAME, False) Then
        BorderHeight = APIDispenser.System.Metrics(SM_CXFRAME)
    Else
        BorderHeight = APIDispenser.System.Metrics(SM_CXEDGE)
    End If
End If

End Property
Public Property Get BorderStyle() As FormBorderStyleConstants

Dim bsThis As FormBorderStyleConstants

    'vbSizableToolWindow
    'vbSizable
    'vbFixedToolWindow
    'vbFixedSingle
    'vbFixedDialog

If Not IsWindowStyleSet(WS_BORDER, False) Then
    bsThis = vbBSNone
Else
    If IsWindowStyleSet(WS_EX_TOOLWINDOW, True) Then
        'Window is a tool window
        If IsWindowStyleSet(WS_THICKFRAME, False) Then
            bsThis = vbSizableToolWindow
        Else
            bsThis = vbFixedToolWindow
        End If
    Else
        'Window is not a tool window
        If IsWindowStyleSet(WS_THICKFRAME, False) Then
            bsThis = vbSizable
        Else
            If IsWindowStyleSet(WS_DLGFRAME, False) Then
                bsThis = vbFixedDialog
            Else
                bsThis = vbFixedSingle
            End If
        End If
    End If
End If

BorderStyle = bsThis

End Property

Public Property Get BorderWidth() As Long

If BorderStyle = vbBSNone Then
    BorderWidth = 0
Else
    If IsWindowStyleSet(WS_THICKFRAME, False) Then
        BorderWidth = APIDispenser.System.Metrics(SM_CYFRAME)
    Else
        BorderWidth = APIDispenser.System.Metrics(SM_CYEDGE)
    End If
End If

End Property

Public Property Get CaptionHeight() As Long

    If IsWindowStyleSet(WS_CAPTION, False) Then
        If IsWindowStyleSet(WS_EX_TOOLWINDOW, True) Then
            CaptionHeight = APIDispenser.System.Metrics(SM_CYSMCAPTION)
        Else
            CaptionHeight = APIDispenser.System.Metrics(SM_CYCAPTION)
        End If
    Else
        CaptionHeight = 0
    End If
    
End Property

Public Property Get ChildWindows() As Collection

Dim colChildren As Collection
Dim wndThis As ApiWindow
Dim PrevHwnd As Long

'\\ Initialise the collection
Set colChildren = New Collection

Set wndThis = Me.GetWindow(GW_CHILD)
If Not (wndThis Is Nothing) Then
    colChildren.Add wndThis
    PrevHwnd = wndThis.hWnd
    Set wndThis = Me.GetWindow(GW_HWNDNEXT, PrevHwnd)
    While Not (wndThis Is Nothing)
        If wndThis.hWnd <> PrevHwnd Then
            colChildren.Add wndThis
            PrevHwnd = wndThis.hWnd
            Set wndThis = Me.GetWindow(GW_HWNDNEXT, PrevHwnd)
        Else
            Set wndThis = Nothing
        End If
    Wend
End If

Set ChildWindows = colChildren

End Property


'
Public Property Get ClassName() As String

Dim sClassname As String
Dim lRet As Long

'\\ Get the class name
sClassname = String$(1024, 0)
lRet = GetClassNameApi(m_hwnd, sClassname, 1024)
If (Err.LastDllError = 0) And (lRet > 0) Then
    ClassName = Left$(sClassname, lRet)
Else
    ReportError Err.LastDllError, "ApiWindow:Classname", GetLastSystemError
End If

End Property

Public Property Get AttachedClipboard() As ApiClipboard

Dim mClipboard As ApiClipboard

Set mClipboard = New ApiClipboard
mClipboard.ParenthWnd = Me.hWnd
Set AttachedClipboard = mClipboard

End Property

Public Property Let ControlBox(ByVal newSetting As Boolean)

If newSetting Then
    SetWindowStyle WS_SYSMENU, False
Else
    UnSetWindowStyle WS_SYSMENU, False
End If

End Property

'\\ --[ControlBox]----------------------------------------------------------------
'\\ This uses the GetWindowLong() call to mimic the operation of the "ControlBox"
'\\ member of a standard VB form, but for any window
'\\ ------------------------------------------------------------------------------
Public Property Get ControlBox() As Boolean

ControlBox = IsWindowStyleSet(WS_SYSMENU, False)

End Property

Public Property Get ControlBoxRectangle() As APIRect

Dim rcThis As New APIRect

With rcThis
    .Right = (Width - BorderWidth)
    .Top = BorderHeight
    If IsWindowStyleSet(WS_EX_TOOLWINDOW, True) Then
        .Bottom = .Top + APIDispenser.System.Metrics(SM_CYSMSIZE)
        .Left = .Right - APIDispenser.System.Metrics(SM_CXSMSIZE)
    Else
        .Bottom = .Top + APIDispenser.System.Metrics(SM_CYSIZE)
        .Left = .Right - APIDispenser.System.Metrics(SM_CXSIZE)
    End If
End With

Set ControlBoxRectangle = rcThis

End Property

'\\ --[CopyText]----------------------------------------------------
'\\ Copies the text from a window (using the clipboard)
'\\ and returns the result as a string.
'\\ ----------------------------------------------------------------
Public Function CopyText() As String

Dim lRet As Long
Dim sText As String

'\\ First copy the text into the clipboard buffer...
lRet = SendMessage(WM_COPY, 0, 0)

'\\ Now get that data out of the clipboard data area...
If Clipboard.GetFormat(vbCFText) Then
    sText = Clipboard.GetText()
End If

CopyText = sText

End Function

Public Property Get DeviceContext() As ApiDeviceContext

Dim lRet As Long

If mDeviceContext Is Nothing Then
    Set mDeviceContext = New ApiDeviceContext
End If
lRet = GetDCApi(m_hwnd)
If Err.LastDllError = 0 And lRet <> 0 Then
    mDeviceContext.hdc = lRet
End If
Set DeviceContext = mDeviceContext

End Property

'\\ --[DeviceContextNC]-------------------------------------------
'\\ This returns the device context for the whole window, including
'\\ the non client area
'\\ ---------------------------------------------------------------
Public Property Get DeviceContextNC() As ApiDeviceContext

Dim lRet As Long

If mDeviceContextNC Is Nothing Then
    Set mDeviceContextNC = New ApiDeviceContext
End If
lRet = GetWindowDC(m_hwnd)
If Err.LastDllError = 0 And lRet <> 0 Then
    mDeviceContextNC.hdc = lRet
End If
Set DeviceContextNC = mDeviceContextNC

End Property


Public Sub DrawMenuBar()

Dim lRet As Long

lRet = DrawMenuBarApi(m_hwnd)
If (lRet = 0) Or (Err.LastDllError > 0) Then
    Call ReportError(Err.LastDllError, "ApiWindow:DrawMenuBar:", GetLastSystemError)
End If

End Sub



Public Function GetParent() As ApiWindow

Dim hWndParent As Long
Dim ParentWindow As ApiWindow

If IsWindowApi(m_hwnd) Then
    hWndParent = GetParentApi(m_hwnd)
    If IsWindowApi(hWndParent) Then
        '\\ If its already subclassed, return that instance...
        Set ParentWindow = AllSubclassedWindows.Item(hWndParent)
        If ParentWindow Is Nothing Then
            '\\ Otherwise create a new instance
            Set ParentWindow = New ApiWindow
            ParentWindow.hWnd = hWndParent
        End If
        Set GetParent = ParentWindow
    End If
End If

End Function


Public Function GetWindow(wCmd As enGetWindow, Optional PrevHwnd As Long) As ApiWindow

Dim hWnd As Long
Dim window As ApiWindow

If PrevHwnd = 0 Then
    hWnd = GetWindowApi(m_hwnd, wCmd)
Else
    hWnd = GetWindowApi(PrevHwnd, wCmd)
End If
If IsWindowApi(hWnd) Then
    '\\ If its already subclassed, return that instance...
    On Error Resume Next
    Set window = AllSubclassedWindows.Item(hWnd)
    On Error GoTo 0
    If window Is Nothing Then
        Set window = New ApiWindow
        window.hWnd = hWnd
    End If
    Set GetWindow = window
End If

End Function

Public Function GetWindowLong(index As enGetWindowLong) As Long

Dim lRet As Long

lRet = GetWindowLongApi(m_hwnd, index)
If Err.LastDllError = 0 Then
    GetWindowLong = lRet
End If

End Function

Public Property Get hdc() As Long

hdc = GetDCApi(m_hwnd)

End Property

Public Property Get Height() As Long

    With RECT
        Height = (.Bottom - .Top)
    End With
    
End Property

'\\ --[HitTest]-------------------------------------------------------------
'\\ Returns the position of the x,y coordinate (in client coordinates)
'\\ in terms of what would be hit if the mouse were clicked there
'\\ ------------------------------------------------------------------------
'\\ (c) 2001 Merrion Computing Ltd
Public Function HitTest(ByVal x As Long, ByVal y As Long) As enHitTestResult

Dim htThis As enHitTestResult

With RECT
    If x < 0 Or y < 0 Or x > Width Or y > Height Then
        htThis = HTNOWHERE
    Else
        If x < BorderWidth Then
            '\\ Somewhere in the lefthand border
            htThis = HTLEFT
        ElseIf x >= (Width - BorderWidth) Then
            '\\ Somewhere in the righthand border
            htThis = HTRIGHT
        Else
            If y < BorderHeight Then
                htThis = HTTOP
            ElseIf y >= Height - BorderHeight Then
                htThis = HTBOTTOM
            ElseIf y <= CaptionHeight Then
                htThis = HTCAPTION
                '\\ If the window has the various caption buttons, test these
                If ControlBox Then
                    If ControlBoxRectangle.ContainsPoint(x, y) Then
                        htThis = HTCLOSE
                    ElseIf SysmenuBoxRectangle.ContainsPoint(x, y) Then
                        htThis = HTSYSMENU
                    End If
                End If
                If MinButton Then
                    If MinimiseBoxRectangle.ContainsPoint(x, y) Then
                        htThis = HTMINBUTTON
                    End If
                End If
                If MaxButton Then
                    If MaximiseBoxRectangle.ContainsPoint(x, y) Then
                        htThis = HTMAXBUTTON
                    End If
                End If
            Else
                htThis = HTCLIENT
            End If
        End If
    End If
End With

HitTest = htThis

End Function

Public Property Get hWnd() As Long

    hWnd = m_hwnd
    
End Property

Public Property Let hWnd(ByVal newHwnd As Long)

Dim lRet As Long

    If newHwnd <> m_hwnd Then
        '\\ Must reset the proc address before closing
        If mOldProcAddress > 0 Then
            lRet = SetWindowLong(GWL_WNDPROC, mOldProcAddress)
            mOldProcAddress = 0
        End If
        '\\ Must unset the menus...
        Set mSystemMenu = Nothing
        Set mMenu = Nothing
        
        m_hwnd = newHwnd
    End If
    
End Property

Public Sub InvalidateRect(ByVal RectIn As APIRect)

Dim rcThis As RECT
Dim lRet As Long

With rcThis
    .Bottom = RectIn.Bottom
    .Left = RectIn.Left
    .Top = RectIn.Top
    .Right = RectIn.Right
End With

lRet = InvalidateRectByPointerApi(m_hwnd, VarPtr(rcThis), True)

End Sub


'\\ --[IsWindowStyleSet]----------------------------------------------------------------------
'\\ Checks for the style bit specified in the window specified.
'\\ ----------------------------------------------------------------------------------------
'\\ (c) 2001 - Merrion Computing.  All rights  to use, reproduce or publish this code reserved
'\\ Please check http://www.merrioncomputing.com for updates.
'\\ ----------------------------------------------------------------------------------------
Public Function IsWindowStyleSet(ByVal TheStyle As enWindowStyles, ByVal Extended As Boolean) As Boolean

Dim lStyle As Long
Dim lWSIndex As Long

If Extended Then
    lWSIndex = GWL_EXSTYLE
Else
    lWSIndex = GWL_STYLE
End If

'\\ Get the current setting of that style bit
lStyle = GetWindowLongApi(m_hwnd, lWSIndex)
IsWindowStyleSet = (lStyle And TheStyle)

End Function





Public Property Let MaxButton(ByVal newSetting As Boolean)

If newSetting Then
    SetWindowStyle WS_MAXIMIZEBOX, False
Else
    UnSetWindowStyle WS_MAXIMIZEBOX, False
End If

End Property

Public Property Get MaxButton() As Boolean

MaxButton = IsWindowStyleSet(WS_MAXIMIZEBOX, False)

End Property

Public Property Get MaximiseBoxRectangle() As APIRect

Dim rcThis As New APIRect

With rcThis
    .Right = (Width - BorderWidth)
    .Top = BorderHeight
    If IsWindowStyleSet(WS_EX_TOOLWINDOW, True) Then
        .Right = .Right - APIDispenser.System.Metrics(SM_CXSMSIZE)
        .Bottom = .Top + APIDispenser.System.Metrics(SM_CYSMSIZE)
        .Left = .Right - APIDispenser.System.Metrics(SM_CXSMSIZE)
    Else
        .Right = .Right - APIDispenser.System.Metrics(SM_CXSIZE)
        .Bottom = .Top + APIDispenser.System.Metrics(SM_CYSIZE)
        .Left = .Right - APIDispenser.System.Metrics(SM_CXSIZE)
    End If
End With

Set MaximiseBoxRectangle = rcThis

End Property

Public Property Get Menu() As ApiMenu

Dim lRet As Long

lRet = GetMenuApi(m_hwnd)
If Err.LastDllError = 0 And lRet > 0 Then
    If mMenu Is Nothing Then
        Set mMenu = New ApiMenu
    End If
    mMenu.hMenu = lRet
    Set Menu = mMenu
End If

End Property





Public Property Let MinButton(ByVal newSetting As Boolean)

If newSetting Then
    SetWindowStyle WS_MINIMIZEBOX, False
Else
    UnSetWindowStyle WS_MINIMIZEBOX, False
End If

End Property

Public Property Get MinButton() As Boolean

MinButton = IsWindowStyleSet(WS_MINIMIZEBOX, False)

End Property

Public Property Get MinimiseBoxRectangle() As APIRect

Dim rcThis As New APIRect

With rcThis
    .Right = (Width - BorderWidth)
    .Top = BorderHeight
    If IsWindowStyleSet(WS_EX_TOOLWINDOW, True) Then
        .Right = .Right - (APIDispenser.System.Metrics(SM_CXSMSIZE) * 2)
        .Bottom = .Top + APIDispenser.System.Metrics(SM_CYSMSIZE)
        .Left = .Right - APIDispenser.System.Metrics(SM_CXSMSIZE)
    Else
        .Right = .Right - (APIDispenser.System.Metrics(SM_CXSIZE) * 2)
        .Bottom = .Top + APIDispenser.System.Metrics(SM_CYSIZE)
        .Left = .Right - APIDispenser.System.Metrics(SM_CXSIZE)
    End If
End With

Set MinimiseBoxRectangle = rcThis

End Property

Public Property Let MouseCapture(ByVal CaptureMouse As Boolean)

Dim lRet As Long

If CaptureMouse Then
    mPrevCapture = SetCaptureApi(m_hwnd)
Else
    lRet = SetCaptureApi(mPrevCapture)
End If

End Property

Public Property Get MouseCapture() As Boolean

MouseCapture = (GetCaptureApi() = m_hwnd)

End Property

Public Property Let MouseHoverTimeout(ByVal newTimeout As Long)

Dim lRet As Long
Dim mheThis As TRACKMOUSESTRUCT

With mheThis
    .cbSize = Len(mheThis)
    .dwFlags = TME_HOVER Or TME_LEAVE
    .hwndTrack = m_hwnd
    .dwHoverTime = newTimeout
End With

If APIDispenser.System.IsRequiredSystem("TrackMouse", ver_Win_98) Then
    lRet = TrackMouseEvent(mheThis)
    If Err.LastDllError Then
        ReportError Err.LastDllError, "ApiWindow:MouseHoverTimeout (Let)", GetLastSystemError
    End If
End If

End Property

Public Property Get MouseHoverTimeout() As Long

Dim lRet As Long
Dim mheThis As TRACKMOUSESTRUCT

With mheThis
    .cbSize = Len(mheThis)
    .dwFlags = TME_QUERY
    .hwndTrack = m_hwnd
End With

If APIDispenser.System.IsRequiredSystem("TrackMouse", ver_Win_98) Then
    lRet = TrackMouseEvent(mheThis)
    If Err.LastDllError Then
        ReportError Err.LastDllError, "ApiWindow:MouseHoverTimeout (get)", GetLastSystemError
    End If
End If

MouseHoverTimeout = mheThis.dwHoverTime

End Property

Friend Property Get OldProcAddress() As Long

    OldProcAddress = mOldProcAddress
    
End Property

Public Property Get RECT() As APIRect

Dim mRect As APIRect
Dim lpRect As RECT
Dim lRet As Long

Set mRect = New APIRect
lRet = GetWindowRectApi(m_hwnd, lpRect)
If Err.LastDllError = 0 Then
    Call mRect.CreateFromPointer(VarPtr(lpRect))
End If
Set RECT = mRect

End Property

Public Sub Refresh()

Dim lRet As Long

lRet = InvalidateRectByPointerApi(m_hwnd, 0, True)

End Sub


Public Property Set Region(ByVal newRegion As ApiRegion)

Dim lRet As Long

If newRegion Is Nothing Then
    Set mRegion = Nothing
Else
    If newRegion.hRgn <> Region.hRgn Then
        Set mRegion = newRegion
        lRet = SetWindowRgn(m_hwnd, mRegion.hRgn, True)
    End If
End If

End Property

Public Property Get Region() As ApiRegion

Dim lRet As Long

If mRegion Is Nothing Then
    Set mRegion = New ApiRegion
End If
lRet = GetWindowRgn(m_hwnd, mRegion.hRgn)
If Err.LastDllError = 0 And lRet > 0 Then
    mRegion.hRgn = lRet
End If
Set Region = mRegion

End Property

Public Sub ScrollWindow(ByVal dX As Long, ByVal dY As Long, ScrollMethod As enScrollWindow)

Dim lRet As Long
Dim lpUpdate As RECT

lRet = ScrollWindowExAPI(m_hwnd, dX, dY, vbNull, vbNull, vbNull, lpUpdate, ScrollMethod)
If Err.LastDllError = 0 Then

Else
    Call ReportError(Err.LastDllError, "ApiWindow:ScrollWindow", GetLastSystemError)
End If

End Sub

'\\ --[SelectedText]----------------------------------------------------------------------------
'\\ Returns the text that is in the currently selected part of this window
'\\ (Allows the imlementation of .SelText on controls that don't have that member)
'\\ ----------------------------------------------------------------------------------------
'\\ (c) 2001 - Merrion Computing.  All rights  to use, reproduce or publish this code reserved
'\\ Please check http://www.merrioncomputing.com for updates.
'\\ ----------------------------------------------------------------------------------------
Public Property Get SelectedText() As String

Dim sSelectedText As String
Dim lSelStart As Integer
Dim lSelEnd As Integer
Dim lRet As Long

Dim lSelMsg As Long

'\\ Select the appropriate message to query the selection according to the window type
If Me.WindowBaseClass = "EDIT" Then
    lSelMsg = EM_GETSEL
ElseIf Me.WindowBaseClass = "COMBOBOX" Then
    lSelMsg = CB_GETEDITSEL
Else
    '\\ If a control supports selected items, it should use the same message
    lSelMsg = EM_GETSEL
End If

lRet = SendMessageByLong(Me.hWnd, lSelMsg, 0, 0)
If Err.LastDllError > 0 Then
    ReportError Err.LastDllError, "ApiWindow:SelectedText", GetLastSystemError
Else
    lSelEnd = APIDispenser.HiWord(lRet)
    lSelStart = APIDispenser.LoWord(lRet)
    sSelectedText = Me.WindowText
    If lSelEnd > 0 Then
        sSelectedText = Left$(sSelectedText, lSelEnd)
    End If
    If lSelStart > 0 And lSelStart < lSelEnd Then
        sSelectedText = Mid$(sSelectedText, lSelStart)
    End If
End If

SelectedText = sSelectedText

End Property

Public Function SendMessage(ByVal wMsg As WindowMessages, ByVal wParam As Long, lParam As Long) As Long

Dim lRet As Long
Dim lThis As Long
Dim sThis As String

lRet = SendMessageLong(m_hwnd, wMsg, wParam, lParam)

If Err.LastDllError = 0 Then
    SendMessage = lRet
End If

End Function

'\\ --[SetWindowStyle]----------------------------------------------------------------------
'\\ Sets the style bit specified to the window specified.  Note that many window style
'\\ bits cannot be used at run time :. use this with caution
'\\ Returns true if it succeeded
'\\ ----------------------------------------------------------------------------------------
'\\ (c) 2001 - Merrion Computing.  All rights  to use, reproduce or publish this code reserved
'\\ Please check http://www.merrioncomputing.com for updates.
'\\ ----------------------------------------------------------------------------------------
Public Function SetWindowStyle(ByVal newStyle As enWindowStyles, ByVal Extended As Boolean) As Boolean

Dim lStyle As Long
Dim lWSIndex As Long
Dim lRet As Long

If Extended Then
    lWSIndex = GWL_EXSTYLE
Else
    lWSIndex = GWL_STYLE
End If

'\\ Get the current setting of that style bit
lStyle = GetWindowLongApi(m_hwnd, lWSIndex)

'\\ Add the new style bit to it
lStyle = lStyle Or newStyle

'\\ Set it to the window
lRet = SetWindowLongApi(m_hwnd, lWSIndex, lStyle)

'\\ For some styles to take effect, the window must be redrawn...
lRet = UpdateWindow(m_hwnd)

SetWindowStyle = Me.IsWindowStyleSet(lStyle, Extended)

End Function

Public Property Get SysmenuBoxRectangle() As APIRect

Dim rcThis As New APIRect

With rcThis
    .Left = BorderWidth
    .Top = BorderHeight
    If IsWindowStyleSet(WS_EX_TOOLWINDOW, True) Then
        .Bottom = .Top + APIDispenser.System.Metrics(SM_CYSMSIZE)
        .Right = .Left + APIDispenser.System.Metrics(SM_CXSMSIZE)
    Else
        .Bottom = .Top + APIDispenser.System.Metrics(SM_CYSIZE)
        .Right = .Left + APIDispenser.System.Metrics(SM_CXSIZE)
    End If
End With

Set SysmenuBoxRectangle = rcThis

End Property

Public Property Get SystemMenu() As ApiMenu

Dim lRet As Long

lRet = GetSystemMenuApi(m_hwnd, False)
If Err.LastDllError = 0 And lRet > 0 Then
    If mSystemMenu Is Nothing Then
        Set mSystemMenu = New ApiMenu
    End If
    mSystemMenu.hMenu = lRet
    Set SystemMenu = mSystemMenu
End If

End Property

Public Property Get Thread() As ApiThread

Dim lRet As Long
Dim lProcess As Long

Dim threadThis As ApiThread

Set threadThis = New ApiThread
lRet = GetWindowThreadProcessId(Me.hWnd, lProcess)
If Err.LastDllError > 0 Then
    ReportError Err.LastDllError, "ApiWindow:Thread", GetLastSystemError
Else
    threadThis.ThreadId = lRet
End If

Set Thread = threadThis

End Property

Friend Property Get ThreadParent() As Long

If mThreadParent <> 0 Then
    ThreadParent = mThreadParent
Else
    mThreadParent = Me.Thread.ThreadId
    ThreadParent = mThreadParent
End If

End Property

Public Property Get TitleBarRectangle() As APIRect

Dim lRet As Long
Dim tiThis As TITLEBARINFO
Dim rcRet As New APIRect

tiThis.cbSize = Len(tiThis)
If APIDispenser.System.IsRequiredSystem("GetTitlebarInfo", ver_Win_Win2000) Then
    lRet = GetTitleBarInfo(m_hwnd, tiThis)
    If Err.LastDllError Then
        ReportError Err.LastDllError, "ApiWindow:TitleBarRect", GetLastSystemError
    End If
    rcRet.CreateFromPointer (VarPtr(tiThis.rcTitleBar))
End If
Set TitleBarRectangle = rcRet

End Property

Friend Sub TriggerEvent(wMsg As WindowMessages, wParam As Long, lParam As Long, bDiscardMsg As Boolean, lWndProcRet As Long)

Dim Cancel As Boolean

Dim lRet As Long

'\\ Used in wm_vscroll and wm_hscroll processing
Dim ScrollMessage As enScrollMessages
Dim ScrollPosition As Long
Static LastHScroll As Long
Static LastVScroll As Long

'\\ Usid in WM_MOVE processing
Dim x As Long
Dim y As Long

    If wMsg = WM_ACTIVATEAPP Then
        '\\ This app is being activetd or deactivated...
        RaiseEvent ActiveApplicationChanged(CBool(wParam), lParam, Cancel)
    
    ElseIf wMsg = WM_CAPTURECHANGED Then
        '\\This window lost mouse capture
        RaiseEvent LostCapture(lParam, Cancel)
    
    ElseIf wMsg = WM_CHAR Then
        '\\ Keypress was intercepted by this window...
        Dim lRepetition As Long
        Dim lScanCode As Long
        Dim bExtendedKey As Boolean
        Dim bAltDown As Boolean
        Dim bAlreadyPressed As Boolean
        Dim bBeingPressed As Boolean
        With APIDispenser
            lRepetition = .GetBits(lParam, 0, 15)
            lScanCode = .GetBits(lParam, 16, 23)
            bExtendedKey = .GetBits(lParam, 24, 24)
            bAltDown = .GetBits(lParam, 29, 22)
            bAlreadyPressed = .GetBits(lParam, 30, 30)
            bBeingPressed = .GetBits(lParam, 31, 31)
        End With
        RaiseEvent KeyPressed(wParam, lRepetition, lScanCode, bExtendedKey, bAltDown, bAlreadyPressed, bBeingPressed, Cancel)
    
    ElseIf wMsg = WM_COMPACTING Then
        '\\ Windows is low on memory and is compacting memory...
        RaiseEvent LowMemory(wParam)
        '\\ It is not sensible to have a cancel option on this
    
    ElseIf wMsg = WM_MOVE Then
        x = APIDispenser.LoWord(lParam)
        y = APIDispenser.HiWord(lParam)
        RaiseEvent Move(x, y, Cancel)
    
    ElseIf wMsg = WM_HSCROLL Then
        '\\ Horizontal scrollbar event has occured
        ScrollMessage = APIDispenser.LoWord(wParam)
        ScrollPosition = APIDispenser.HiWord(wParam)
        RaiseEvent HorizontalScroll(ScrollMessage, ScrollPosition, Cancel)
        Call Me.ScrollWindow(ScrollPosition - LastHScroll, 0, SW_SCROLLCHILDREN)
        LastHScroll = ScrollPosition
        
    ElseIf wMsg = WM_VSCROLL Then
        '\\ Vertical scrollbar event has occured
        ScrollMessage = APIDispenser.LoWord(wParam)
        ScrollPosition = APIDispenser.HiWord(wParam)
        RaiseEvent VerticalScroll(ScrollMessage, ScrollPosition, Cancel)
        Call Me.ScrollWindow(0, ScrollPosition - LastVScroll, SW_SCROLLCHILDREN)
        LastVScroll = ScrollPosition
        
    ElseIf wMsg = WM_HOTKEY Then
        Dim hkThis As ApiHotkey
        Set hkThis = New ApiHotkey
        hkThis.VKey = APIDispenser.HiWord(lParam)
        hkThis.Modifier = APIDispenser.LoWord(lParam)
        RaiseEvent Hotkey(hkThis)
        Set hkThis = Nothing
        
    ElseIf wMsg = WM_SETTINGCHANGE Then
        RaiseEvent WindowsSettingsChanged(wParam)
    
    ElseIf wMsg = WM_WININICHANGE Then
        Dim sSection As String
        sSection = StringFromPointer(lParam, 1024)
        RaiseEvent WindowsINIChanged(sSection)
        
    '\\ Mouse button down
    ElseIf wMsg = WM_NCLBUTTONDOWN Then
        x = APIDispenser.LoWord(lParam)
        y = APIDispenser.HiWord(lParam)
        RaiseEvent NonClientMouseDown(wParam, vbLeftButton, x, y)
        
    ElseIf wMsg = WM_NCMBUTTONDOWN Then
        x = APIDispenser.LoWord(lParam)
        y = APIDispenser.HiWord(lParam)
        RaiseEvent NonClientMouseDown(wParam, vbMiddleButton, x, y)
        
    ElseIf wMsg = WM_NCRBUTTONDOWN Then
        x = APIDispenser.LoWord(lParam)
        y = APIDispenser.HiWord(lParam)
        RaiseEvent NonClientMouseDown(wParam, vbRightButton, x, y)
        
    '\\ Mouse button up
    ElseIf wMsg = WM_NCLBUTTONUP Then
        x = APIDispenser.LoWord(lParam)
        y = APIDispenser.HiWord(lParam)
        RaiseEvent NonClientMouseUp(wParam, vbLeftButton, x, y)
        
    ElseIf wMsg = WM_NCMBUTTONUP Then
        x = APIDispenser.LoWord(lParam)
        y = APIDispenser.HiWord(lParam)
        RaiseEvent NonClientMouseUp(wParam, vbMiddleButton, x, y)
        
    ElseIf wMsg = WM_NCRBUTTONUP Then
        x = APIDispenser.LoWord(lParam)
        y = APIDispenser.HiWord(lParam)
        RaiseEvent NonClientMouseUp(wParam, vbRightButton, x, y)

    '\\ Mouse move
    ElseIf wMsg = WM_NCMOUSEMOVE Then
        x = APIDispenser.LoWord(lParam)
        y = APIDispenser.HiWord(lParam)
        RaiseEvent NonClientMouseMove(wParam, x, y)
        '\\ If the mouse moved over a menu...
        If wParam = HTMENU Then
            Dim sCaption As String
            Dim ptThis As APIPoint
            Set ptThis = New APIPoint
            With ptThis
                .x = x
                .y = y
            End With
            sCaption = Me.Menu.CaptionFromPoint(Me, ptThis)
            If sCaption <> "" Then
                RaiseEvent MouseOverMenu(sCaption)
            End If
        End If

    '\\ Minimum and maximum info.....
    ElseIf wMsg = WM_GETMINMAXINFO Then
        Dim myMinMaxInfo As MINMAXINFO
        Dim lMaxHeight As Long, lMaxWidth As Long
        Dim lMaxPositionTop As Long
        Dim lMaxPositionLeft As Long
        Dim lMinTrackWidth As Long, lMinTrackheight As Long
        Dim lMaxTrackWidth As Long, lMaxTrackHeight As Long
        Call CopyMemoryMinMaxInfo(myMinMaxInfo, lParam, LenB(myMinMaxInfo))
        If Err.LastDllError <> 0 Then
            ReportError Err.LastDllError, "ApiWindow:WM_GETMINMAXINFO", GetLastSystemError
        Else
            With myMinMaxInfo
                '\\ Maximum height and width
                lMaxWidth = .ptMaxSize.x
                lMaxHeight = .ptMaxSize.y
                '\\ Maximum left and top
                lMaxPositionLeft = .ptMaxPosition.x
                lMaxPositionTop = .ptMaxPosition.y
                '\\ Maxiumum track size
                lMaxTrackWidth = .ptMaxTrackSize.x
                lMaxTrackHeight = .ptMaxTrackSize.y
                '\\ Minimum track size
                lMinTrackWidth = .ptMinTrackSize.x
                lMinTrackheight = .ptMinTrackSize.y
            End With
            RaiseEvent MinMaxSize(lMaxHeight, lMaxWidth, lMaxPositionTop, lMaxPositionLeft, lMinTrackWidth, lMinTrackheight, lMaxTrackWidth, lMaxTrackHeight)
            With myMinMaxInfo
                '\\ Maximum height and width
                 .ptMaxSize.x = lMaxWidth
                 .ptMaxSize.y = lMaxHeight
                '\\ Maximum left and top
                 .ptMaxPosition.x = lMaxPositionLeft
                 .ptMaxPosition.y = lMaxPositionTop
                '\\ Maxiumum track size
                 .ptMaxTrackSize.x = lMaxTrackWidth
                 .ptMaxTrackSize.y = lMaxTrackHeight
                '\\ Minimum track size
                 .ptMinTrackSize.x = lMinTrackWidth
                 .ptMinTrackSize.y = lMinTrackheight
            End With
            Call CopyMinMaxToMemoryInfo(lParam, myMinMaxInfo, LenB(myMinMaxInfo))
        End If
    '\\ Paint event
    ElseIf wMsg = WM_PAINT Then
        '\\ lParam and wParam are not used
        Dim mUpdateRect As New EventVB.APIRect
        Dim rcThis As RECT
        Call GetUpdateRect(m_hwnd, rcThis, False)
        mUpdateRect.CreateFromPointer (VarPtr(rcThis))
        RaiseEvent Paint(mUpdateRect)

        
    ElseIf wMsg = WM_NCPAINT Then
        '\\ wParam is the handle to the update region or 1 if the whole non client
        '\\ area needs to be updated
        Dim dcThis As New ApiDeviceContext
        If wParam = 1 Then
            dcThis.hdc = Me.DeviceContextNC.hdc
        Else
            dcThis.hdc = GetDCEx(m_hwnd, wParam, (DCX_WINDOW Or DCX_INTERSECTRGN))
        End If
        RaiseEvent NonClientPaint(dcThis)

    '\\ Non client hit test
    ElseIf wMsg = WM_NCHITTEST Then
        Dim RetVal As enHitTestResult
        Dim Override As Boolean
                
        '\\ Adjust x and y to map to the non client rectangle
        x = APIDispenser.LoWord(lParam)
        y = APIDispenser.HiWord(lParam)
        With Me.RECT
            x = x - .Left
            y = y - .Top
        End With
        
        RaiseEvent HitTest(x, y, RetVal, Override)
        
        If Override Then
            Cancel = RetVal
            bDiscardMsg = True
        End If

    Else
        '\\ For all other events
        RaiseEvent WindowMessageFired(wMsg, wParam, lParam, bDiscardMsg, lWndProcRet)
    End If
    
    lWndProcRet = Cancel
    
End Sub

'\\ --[UnSetWindowStyle]----------------------------------------------------------------------
'\\ Unets the style bit specified to the window specified.  Note that many window style
'\\ bits cannot be used at run time :. use this with caution
'\\ Returns true if it succeeded
'\\ ----------------------------------------------------------------------------------------
'\\ (c) 2001 - Merrion Computing.  All rights  to use, reproduce or publish this code reserved
'\\ Please check http://www.merrioncomputing.com for updates.
'\\ ----------------------------------------------------------------------------------------
Public Function UnSetWindowStyle(ByVal newStyle As enWindowStyles, ByVal Extended As Boolean) As Boolean

Dim lStyle As Long
Dim lWSIndex As Long
Dim lRet As Long

If Extended Then
    lWSIndex = GWL_EXSTYLE
Else
    lWSIndex = GWL_STYLE
End If

'\\ Get the current setting of that style bit
lStyle = GetWindowLongApi(m_hwnd, lWSIndex)

'\\ Add the new style bit to it
If IsWindowStyleSet(newStyle, Extended) Then
    lStyle = lStyle Xor newStyle
End If

'\\ Set it to the window
lRet = SetWindowLongApi(m_hwnd, lWSIndex, lStyle)

'\\ Refresh the window
lRet = UpdateWindow(m_hwnd)

UnSetWindowStyle = Not (IsWindowStyleSet(lStyle, Extended))

End Function
Public Property Get Enabled() As Boolean

    Enabled = IsWindowEnabledApi(m_hwnd)
    
End Property

Public Property Get Unicode() As Boolean

    Unicode = IsWindowUnicodeApi(m_hwnd)
    
End Property

Public Property Get Visible() As Boolean

    Visible = IsWindowVisibleApi(m_hwnd)
    
End Property



Public Property Get IsZoomed() As Boolean

    IsZoomed = IsZoomedApi(m_hwnd)
    
End Property

Public Property Get Key() As String

    Key = "HWND:" & m_hwnd

End Property

Public Function SetWindowLong(ByVal index As enGetWindowLong, ByVal NewValue As Long) As Long

Dim lRet As Long

lRet = SetWindowLongApi(m_hwnd, index, NewValue)
If Err.LastDllError = 0 Then
    If index = GWL_WNDPROC Then
        '\\ We must store old proc address...
        mOldProcAddress = lRet
    End If
    SetWindowLong = lRet
End If

End Function

Public Property Get Width() As Long

    With RECT
        Width = (.Right - .Left)
    End With
    
End Property

'\\ --[WindowBaseClass]----------------------------------------------------
'\\ Returns the base class of this window
'\\ -----------------------------------------------------------------------
Public Property Get WindowBaseClass() As String

Dim sClass As String

sClass = Me.ClassName

Select Case sClass
Case "BUTTON", "ThunderCheckBox", "ThunderRTCheckBox", _
     "ThunderCommandButton", "ThunderRTCommandButton", _
     "ThunderFrame", "ThunderRTFrame", _
     "ThunderOptionButton", "ThunderRTOptionButton"
    '\\ Classes derived from the BUTTON base class
    WindowBaseClass = "BUTTON"
Case "COMBOBOX", "ThunderComboBox", "ThunderRTComboBox", _
     "ThunderDriveListBox", "ThunderRTDriveListBox"
    
    '\\ Classes derived from the COMBOBOX base class
    WindowBaseClass = "COMBOBOX"
Case "LISTBOX", _
     "ThunderDirListBox", "ThunderRTDirListBox", _
     "ThunderListBox", "ThunderRTListBox", _
     "ThunderFileListBox", "ThunderRTFileListBox"
     
    '\\ Classes derived from the LISTBOX base class
    WindowBaseClass = "LISTBOX"
Case "SCROLLBAR", _
    "ThunderVScrollBar", "ThunderRTVScrollBar", _
    "ThunderHScrollBar", "ThunderRTHScrollBar"
    
    '\\ Classes derived from the SCROLLBAR base class
    WindowBaseClass = "SCROLLBAR"
Case "EDIT", _
     "ThunderTextBox", "ThunderRTTextBox"
    '\\ Classes derived from the SCROLLBAR base class
    WindowBaseClass = "EDIT"
Case Else
    WindowBaseClass = "STATIC"
End Select

End Property

Public Function WindowFromPoint(ByVal xPoint As Long, ByVal yPoint As Long) As ApiWindow

Dim hWnd As Long
Dim window As ApiWindow

hWnd = WindowFromPointApi(xPoint, yPoint)
If IsWindowApi(hWnd) Then
    Set window = New ApiWindow
    window.hWnd = hWnd
    Set WindowFromPoint = window
End If

End Function


Public Property Get WindowText() As String

Dim lRet As Long

Dim sRet As String

lRet = Me.SendMessage(WM_GETTEXTLENGTH, 0, 0)
If lRet > 0 Then
    sRet = String$(lRet + 1, 0)
    lRet = SendMessageByString(m_hwnd, WM_GETTEXT, Len(sRet), sRet)
    '\\ Returns length up to NULL terminator
    If lRet > 0 Then
        sRet = Left$(sRet, lRet)
    End If
ElseIf Err.LastDllError > 0 Then
    ReportError Err.LastDllError, "ApiWindow:WindowText", GetLastSystemError
Else
    sRet = String$(1024, 0)
    lRet = GetWindowTextApi(m_hwnd, sRet, Len(sRet))
    sRet = Left$(sRet, lRet)
End If

WindowText = sRet

End Property

Public Property Get WNDCLASS() As APIWndClass

If mWndClass Is Nothing Then
    Set mWndClass = New APIWndClass
End If
If mWndClass.CreateFromClassname(vbNull, Me.ClassName) Then
    Set WNDCLASS = mWndClass
End If

End Property

Private Sub Class_Terminate()

    '\\ If the old proc address is set, unhook this...
    If mOldProcAddress > 0 Then
        Call SetWindowLong(GWL_WNDPROC, mOldProcAddress)
    End If

    
    Set mMenu = Nothing
    Set mSystemMenu = Nothing
    Set mWndClass = Nothing
    Set mRegion = Nothing
    Set mDeviceContext = Nothing
    Set mDeviceContextNC = Nothing
    
End Sub

